# pyoffwiki - offline wikipedia browser for the Irex Iliad
# written by Amir Shimoni
# put into the public domain for any use
#   but please give credits to those who deserve them...

import string,cgi,time
from os import curdir, sep
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from xml.sax.saxutils import escape
import codecs
import urllib
import sys
from mwlib import uparser, htmlwriter
import bz2wiki
import StringIO
import traceback

tdf = open("datafile.txt")
mainfilename = tdf.readline().strip()
tdf.close()
tdf = None
db = bz2wiki.Bz2WikiDB(mainfilename)

class OutStreamEncoder(object):
    """Wraps a stream with an encoder
    """

    def __init__(self, outstream, encoding=None):
        self.out = outstream
        if not encoding:
            self.encoding = sys.getfilesystemencoding()
        else:
            self.encoding = encoding

    def write(self, obj):
        """Wraps the output stream, encoding Unicode
        strings with the specified encoding"""

        if isinstance(obj, unicode):
            self.out.write(obj.encode(self.encoding))
        else:
            self.out.write(obj)

    def __getattr__(self, attr):
        """Delegate everything but write to the stream"""

        return getattr(self.out, attr)

class MyHandler:
    def __init__(self):
        self.searchtitle = '?search='
        self.search_html='''
<form method='GET' action='/'>
Find in Wiki (exact match only!):
<input type=text name=search>
<input type=submit name=type value=search> 
<input type=submit name=type value=browse> 
'''
        self.enable_temp_html='<a href="/?enabletemplates">Enable Templates</a> '
        self.disable_temp_html='<a href="/?disabletemplates">Disable Templates</a> '
        self.random_html='<a href="/?random">Random Page</a> '
        self.bratt = "?browseat="

        self.notfound_html='Topic not found';
        self.templates_enabled=False
        self.p = None


    def showPage(self, filename):
        f = open(filename)
        self.p.send_response(200)
        self.p.send_header('Content-type',	'text/html; charset=UTF-8')
        self.p.end_headers()
        self.p.wfile.write(f.read())
        f.close()
        return

    def showHeader(self):
        self.p.send_response(200)
        self.p.send_header('Content-type',	'text/html; charset=UTF-8')
        self.p.end_headers()
        return

    def doRedirect(self, location):
        txt = """\
                <html>
                   <head><title>302 Found</title></head>
                   <body>302 Found <a href="%s">here</a>.</body>
                </html>\n""" % location
        self.p.send_response (302)
        self.p.send_header ("Location", location)
        #self.p.send_header ("Cache-Control", "private")
        #self.p.send_header ("Pragma", "no-cache")
        #self.p.send_header ("Expires", "Sun, 01 Jul 1970 00:00:00 GMT")
        self.p.send_header ("Content-type", "text/html")
        self.p.send_header ("Content-Length", str (len (txt)))
        self.p.end_headers ()
        self.p.wfile.write (txt)
        return

    def showTopOfPage(self, isMore_):
        self.showHeader()
        self.p.wfile.write(self.search_html)
        self.p.wfile.write(self.templates_enabled and self.disable_temp_html or self.enable_temp_html)
        self.p.wfile.write(self.random_html)
        if isMore_:
            self.p.wfile.write('<a href="'+isMore_+'">Show next match</a> ')

        self.p.wfile.write('</form><br/>')

    
    def do_GET(self, p_):
        self.p = p_
        db.setTemplates(self.templates_enabled)

        title = self.p.path.strip('/')
        if title.startswith('../'):
            title = title[3:]

        if title == '?enabletemplates':
            self.templates_enabled=True
            title='';

        if title == '?disabletemplates':
            self.templates_enabled=False
            title='';

        if title == "?random":
            title = db.getRandomTitle()


        if title.startswith(self.searchtitle):
            typeind = title.find("&type=")
            stype = title[typeind+6:]
            title = title[len(self.searchtitle):typeind]
            title = unicode(urllib.unquote_plus(title), "utf8").lower()
            title = unicode.encode(title, "utf8")
            if stype == 'search':
                return self.doRedirect("/"+title)
            else:
                #somepos = db.getCdbSearch(urllib.unquote_plus(title).lower())
                somepos = db.getCdbSearch(title);
                return self.doRedirect("/"+self.bratt + str(somepos))


        if title.startswith(self.bratt):
            try:
                startpos = int(title[len(self.bratt):])

                res = db.getCdbListAt(startpos, 28)
                self.showTopOfPage(False)
                self.p.wfile.write('<br/><br/><a href="/'+self.bratt+str(2*startpos - res[1])+'">View Previous (Approx)</a><br/><br/>\n')
                for a in res[0]:
                    self.p.wfile.write('<a href="/'+urllib.quote(a)+'">'+a+'</a><br/>\n')
                self.p.wfile.write('<br/><br/><a href="/'+self.bratt+str(res[1])+'">View More</a><br/>\n')
                return
            except:
                self.showTopOfPage(False)
                self.p.wfile.write(self.notfound_html)
                self.p.wfile.write('<pre>'+traceback.format_exc()+'</pre>')
                return
            return

            

        if title == '':
            self.showTopOfPage(False)
            return 
        else:
            title = unicode(urllib.unquote_plus(title), "utf8").lower()
            title = unicode.encode(title, "utf8")
            try:
                #r=uparser.parseString(title, wikidb=db)
                r=db.getParsedArticle(title, uparser)
            except:
                self.showTopOfPage(False)
                self.p.wfile.write(self.notfound_html)
                self.p.wfile.write('<pre>'+traceback.format_exc()+'</pre>')
                return;

            if db.isMoreArticles(title):
                self.showTopOfPage("/"+title+".")
            else:
                self.showTopOfPage(False)

            #out=StringIO.StringIO()
            #self.p.wfile.write(cgi.escape('\xc3\xa9'))
            #htmlwriter.HTMLWriter(out).write(r)
            #self.p.wfile.write(out.getvalue()) #.encode('utf-8'))
            htmlwriter.HTMLWriter(OutStreamEncoder(self.p.wfile)).write(r)
            #out.close()
            return
        
_theActualHandler = MyHandler()

class MyHandlerProxy(BaseHTTPRequestHandler):
    def do_GET(self):
        try:
            _theActualHandler.do_GET(self)
        except:
            self.wfile.write("Error!")
            self.wfile.write('<pre>'+traceback.format_exc()+'</pre>')

def main():
    try:
        server = HTTPServer(('', 8080), MyHandlerProxy)
        print 'started httpserver...'
        server.serve_forever()
    except KeyboardInterrupt:
        print '^C received, shutting down server'
        server.socket.close()

if __name__ == '__main__':
    main()
